<?php defined('SYSPATH') or die('No direct script access.');

abstract class Apartment {

	/**
	 * @var   string     default driver to use
	 */
	public static $default = 'cian';

	/**
	 * @var   Kohana_Cache instances
	 */
	public static $instances = array();

	/**
	 * Creates a singleton of a Kohana Cache group. If no group is supplied
	 * the __default__ cache group is used.
	 *
	 *     // Create an instance of the default group
	 *     $default_group = Cache::instance();
	 *
	 *     // Create an instance of a group
	 *     $foo_group = Cache::instance('foo');
	 *
	 *     // Access an instantiated group directly
	 *     $foo_group = Cache::$instances['default'];
	 *
	 * @param   string  $group  the name of the cache group to use [Optional]
	 * @return  Cache
	 * @throws  Cache_Exception
	 */
	public static function instance($group = NULL)
	{
		// If there is no group supplied
		if ($group === NULL)
		{
			// Use the default setting
			$group = Apartment::$default;
		}

		if (isset(Apartment::$instances[$group]))
		{
			// Return the current group if initiated already
			return Apartment::$instances[$group];
		}

		$config = Kohana::$config->load('apartment');

		if ( ! $config->offsetExists($group))
		{
			throw new Apartment_Exception(
				'Failed to load Apartment group: :group',
				array(':group' => $group)
			);
		}

		$config = $config->get($group);

		// Create a new cache type instance
		$apartment_class = 'Apartment_'.ucfirst($config['driver']);
		Apartment::$instances[$group] = new $apartment_class($config);

		// Return the instance
		return Apartment::$instances[$group];
	}

	/**
	 * @var  Config
	 */
	protected $_config = array();

	/**
	 * Ensures singleton pattern is observed, loads the default expiry
	 *
	 * @param  array  $config  configuration
	 */
	protected function __construct(array $config)
	{
		$this->config($config);
	}

	/**
	 * Getter and setter for the configuration. If no argument provided, the
	 * current configuration is returned. Otherwise the configuration is set
	 * to this class.
	 *
	 *     // Overwrite all configuration
	 *     $cache->config(array('driver' => 'memcache', '...'));
	 *
	 *     // Set a new configuration setting
	 *     $cache->config('servers', array(
	 *          'foo' => 'bar',
	 *          '...'
	 *          ));
	 *
	 *     // Get a configuration setting
	 *     $servers = $cache->config('servers);
	 *
	 * @param   mixed    key to set to array, either array or config path
	 * @param   mixed    value to associate with key
	 * @return  mixed
	 */
	public function config($key = NULL, $value = NULL)
	{
		if ($key === NULL)
			return $this->_config;

		if (is_array($key))
		{
			$this->_config = $key;
		}
		else
		{
			if ($value === NULL)
				return Arr::get($this->_config, $key);

			$this->_config[$key] = $value;
		}

		return $this;
	}

	abstract public function write($data);
	abstract public function read($id, $data, $lifetime = 3600);
}